/*
 * GeoVISTA Center (Penn State, Dept. of Geography)
 * Copyright (c) 2002, GeoVISTA Center
 * Licensed under Simplified BSD License
 * This library is developed and distributed for free usage,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * You can redistribute and/or modify it under the terms of the
 * Simplified BSD License
 *
 *
 *
 *
 *
 *
 *
 * @original author: jin Chen 
 * @author: jin Chen 
 * @date: Nov 19, 2008$
 * @version: 1.0
 */
package edu.psu.geovista.app.vit.pub.components.ptnbskt;

import edu.psu.geovista.common.utils.collection.CollectionUtils;
import edu.psu.geovista.ui.event.SelectionEvent;
import edu.psu.geovista.ui.event.SelectionListener;
import org.apache.commons.collections.map.ListOrderedMap;

import javax.swing.*;
import javax.swing.event.EventListenerList;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import java.util.*;

public class MySelectionTable extends JTable {
    Map Id2Index;
    Map<Object, Set> dataGroups =new ListOrderedMap();
    String columnName_ID="ID";
     protected int IdColumnIndex = 0;
    boolean fireSelectionEvents=true;
    protected EventListenerList listenerList = new EventListenerList();
      public Map<Object, Properties> getTableAttrbites(){
        int rowcount = this.getRowCount();
        Map<Object, Properties> map=new HashMap<Object, Properties>();
        for (int i=0;i<rowcount;i++){
            Object id = this.getValueAt(i, "ID");
            Object desc = this.getValueAt(i, "Description");
            Properties attrs=new Properties();//attributes of the row
            attrs.put("Description",desc);
            map.put(id,attrs);

        }
        return map;
    }
    public Object getValueAt(int row, String columnName) {
        int col = ((MyTableModel) this.getModel()).getColumnIndex(columnName);
        return this.getValueAt(row, col);
    }
     public int[] getSelectedDataIndexs() {
        int[] sel = getSelectedRows();
        return getSelectedDatatIndexs(sel);
    }
    public  int[] getSelectedDatatIndexs(int[] selrows) {
        Set selectedIds = this.getSelectedId(selrows);
        int[] selectedDataindex = getSelectedDataIndex(selectedIds);
        return selectedDataindex;

    }
     public  Set getSelectedId(int[] selectedRows){
        TableColumn tableColumn = getColumn("ID");
        int columnIndex = tableColumn.getModelIndex();
        //Set dataIndexs=new HashSet();
        Set ids=new HashSet();
        Object id =null;
        for (int i=0;i<selectedRows.length ;i++){
            int row = selectedRows[i];  //selected row
            id = getValueAt(row, columnIndex); // selected location/cluster ID display on the table
            ids.add(id);

        }
        return ids;
    }
    public  int[] getSelectedDataIndex(Set selectedClusterIds){
        Map<Object,Set> dataGroups = this.getDataGroups();
        Set dataIndexs=new HashSet();
        for (Iterator iterator = selectedClusterIds.iterator(); iterator.hasNext();) {
            Object groupId = (Object) iterator.next();
            Set mbrDataIndex = dataGroups.get(groupId) ;  //member data indexs
            dataIndexs.addAll(mbrDataIndex);
        }
        int[] dataindexs = CollectionUtils.convert2IntArray(dataIndexs);
        return dataindexs;
    }

    /**
     * return the union of the selected data indexs
     * @return
     */
    public int[] getSelectedUnionDataIndex(Set selectedClusterIds){
         Map<Object,Set> dataGroups = this.getDataGroups();
        Set dataIndexs=new HashSet();
        for (Iterator iterator = selectedClusterIds.iterator(); iterator.hasNext();) {
            Object groupId = (Object) iterator.next();
            Set mbrDataIndex = dataGroups.get(groupId) ;  //member data indexs
            if(dataIndexs.size() ==0)
                dataIndexs.addAll(mbrDataIndex);
            else
                dataIndexs.retainAll(mbrDataIndex);

        }
        int[] dataindexs = CollectionUtils.convert2IntArray(dataIndexs);
        return dataindexs;

    }
     public void valueChanged(ListSelectionEvent e) {
        super.valueChanged(e);
        if(isFireSelectionEvents() ){
        fireEvents();
        }
    }
    /***
     *   
     *   
     */
    protected void update(Object groupId, Set datagroup){    // 
        Object[] arow=new Object[]{groupId,datagroup.size(),""};
        this.addRow(arow);
    }
     public void addRow(Object[] rowData) {
        int lastRow = dataModel.getRowCount();
       ((MyTableModel) dataModel).insertRow(lastRow, rowData);
    }
    public void setDataGroups( Map<Object, Set> dgs,Map<Object, Properties> dps) {
        setDataGroups(dgs);
        this.removeAllRow();
        Set<Object> keys = dgs.keySet();
        List keylist=new ArrayList(keys);
        Collections.sort(keylist);
        for (Iterator iterator = keylist.iterator(); iterator.hasNext();) {
            Object key = (Object) iterator.next();
            Set set = dgs.get(key);
            Object desc = "";
            if(dps!=null){
                Properties props = dps.get(key);
                if(props!=null)
                desc = props.get( "Description");
            }
            Object[] arow=new Object[]{key,set.size(),desc};
            this.addRow(arow);

        }
    }
      public void removeAllRow() {
        ((MyTableModel) this.getModel()).removeAllRow();
    }
    protected void updateOnRemoving(Object groupId){

    }
     public static MySelectionTable getDefaultSelectionTable(){
        MySelectionTable table=new MySelectionTable();
         Object[][] data = {
/*                {null, null, null, null},
                {null, null, null, null},*/
                {null, null, null, null}};
        String[] colnames = {
                "ID", "SIZE",  "Description"
        };
        boolean[] editable={false,true,false};
        MyTableModel model = new MyTableModel(colnames,0);
        //model.setEditables(editable);
        table.setModel(model);

        return  table;
    }

    public Map getId2Index() {
        return Id2Index;
    }

    public Map<Object, Set> getDataGroups() {
        return dataGroups;
    }

    public String getColumnName_ID() {
        return columnName_ID;
    }

    public int getIdColumnIndex() {
        return IdColumnIndex;
    }

    public boolean isFireSelectionEvents() {
        return fireSelectionEvents;
    }

    public EventListenerList getListenerList() {
        return listenerList;
    }

    public void setDataGroups(Map<Object, Set> dataGroups) {
        this.dataGroups = dataGroups;
    }
    public void addDataGroup(Object groupId, Set datagroup){
        if(groupId==null){
            groupId=this.getId();
        }
        dataGroups.put(groupId,datagroup);
        update(groupId,datagroup);
    }
     private Object getId(){// 
        int size = this.dataGroups.size();
        int myid=1;
        Set<Object> keys = dataGroups.keySet();
        for (Iterator objectIterator = keys.iterator(); objectIterator.hasNext();) {
            Object key = (Object) objectIterator.next();
            if (key instanceof Integer ){
                int akey = ((Integer) key).intValue();
                if (akey>=myid){
                    myid=akey+1; // 
                }
            }
        }
        return myid;
    }
    public void setValueAt(Object aValue, int row, String columnName) {

        int col = ((MyTableModel) this.getModel()).getColumnIndex(columnName);
        this.setValueAt(aValue, row, col);
    }

    /**
      * adds an SelectionListener
      */
           public void addSelectionListener (SelectionListener l) {
              listenerList.add(SelectionListener.class, l);
           }

           /**
            * removes an SelectionListener from the component
            */
           public void removeSelectionListener (SelectionListener l) {
               listenerList.remove(SelectionListener.class, l);
           }


     public void removeRows(int[] rows){
        Arrays.sort(rows);
        for (int i=rows.length -1;i>=0;i--){
            int row = rows[i];
            Object id = this.getValueAt(row, this.getColumnName_ID());
            removeRow(rows[i]);
            dataGroups.remove(id);
        }
     }

    public void removeRow(int row) {
        ((MyTableModel) this.dataModel).removeRow(row);
    }
     public   void fireEvents() { // 
        int[] selectedDataindex = getSelectedDataIndexs();

        Object[] listeners = listenerList.getListenerList();
        SelectionEvent e = null;
        // Process the listeners last to first, notifying
        // those that are interested in this event
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == SelectionListener.class) {
                // Lazily create the event:
                if (e == null) {
                    e=new SelectionEvent(this, selectedDataindex,selectedDataindex);
                    //e =new SelectionEvent(getSrc(), lowLevelSelection); //new PcpSelectionEvent(this, newSelection);

                    //e.setMode(mode);
                }
                ((SelectionListener)listeners[i + 1]).selectionChanged(e);
            }
        }//next i
    }

    public void setId2IndexMap(Map id2Index) {
        Id2Index = id2Index;
    }

    static class MyTableModel extends DefaultTableModel{
        MyTableModel() {
        }

        MyTableModel(int rowCount, int columnCount) {
            super(rowCount, columnCount);
        }

        MyTableModel(Vector columnNames, int rowCount) {
            super(columnNames, rowCount);
        }

        MyTableModel(Object[] columnNames, int rowCount) {
            super(columnNames, rowCount);
        }

        MyTableModel(Vector data, Vector columnNames) {
            super(data, columnNames);
        }

        MyTableModel(Object[][] data, Object[] columnNames) {
            super(data, columnNames);
        }

        public int getColumnIndex(String name){
        return this.columnIdentifiers.indexOf(name);
    }
          public void removeAllRow() {
        while(this.getRowCount() >0){
            this.removeRow(this.getRowCount() -1);
        }
    }
    }
    
}
